package log

import (
	"fmt"
	"gitee.com/kirile/color"
	"gitee.com/kirile/log/logfile"
	"os"
)

// LogFile ...
type Logger struct {
	Receivers []*Receiver
	Active    bool
}

type CallDepth int

const (
	LibUseCallDepth  CallDepth = 5 //将此日志库进行一层包装时, CallDepth需要+1
	DefaultCallDepth CallDepth = 4 //直接使用此日志库时, 为4
)

type Option struct {
	ConsoleLevel Level
	FileLevel    Level
	LogDir       string
	Prefix       string
	IsLib        bool
	Zip          bool
	MaxMegaBytes int
	MaxCount     int
	MaxAge       int
}

// NewLogger ...
func NewLogger(opt Option) (*Logger, error) {
	l := &Logger{}
	var err error

	//终端输出
	consoleRec := NewReceiver(color.NewColorableStdout(), "["+opt.Prefix+"]")
	consoleRec.Color = true
	consoleRec.Level = opt.ConsoleLevel
	if !opt.IsLib {
		consoleRec.CallDepth = int(DefaultCallDepth)
	} else {
		consoleRec.CallDepth = int(LibUseCallDepth)
	}

	err = os.MkdirAll(opt.LogDir, os.ModePerm)
	if err != nil {
		return nil, err
	}
	mmb := opt.MaxMegaBytes
	mb := opt.MaxCount
	ma := opt.MaxAge
	if opt.MaxMegaBytes == 0 {
		mmb = 10
	}
	if opt.MaxAge == 0 {
		ma = 7
	}
	if opt.MaxCount == 0 {
		mb = 5
	}

	logFile := &logfile.LogFile{
		Filename:   opt.LogDir + "/" + opt.Prefix + ".log",
		MaxSize:    mmb, // megabytes
		MaxBackups: mb,
		LocalTime:  true,
		MaxAge:     ma,      //days
		Compress:   opt.Zip, // disabled by default
	}

	fileRec := NewReceiver(logFile, "["+opt.Prefix+"]")
	fileRec.Level = opt.FileLevel
	fileRec.Color = false
	fileRec.CallDepth = consoleRec.CallDepth
	fileRec.Format = "%s: %s"
	l.Receivers = []*Receiver{consoleRec, fileRec}
	l.Active = true
	return l, nil
}

// SetLevel sets the log level of ALL receivers
func (l *Logger) SetLevel(lvl Level) {
	for _, r := range l.Receivers {
		r.Level = lvl
	}
}

// SetPrefix sets the prefix of ALL receivers
func (l *Logger) SetPrefix(prefix string) {
	for _, r := range l.Receivers {
		r.SetPrefix(prefix)
	}
}

// Write to all Receivers
func (l *Logger) logAll(opt *levelOptions, s string) {
	// Skip everything if logger is disabled
	if !l.Active {
		return
	}
	// Log to all receivers
	for _, r := range l.Receivers {
		r.log(opt, s)
	}
}

// Debug logs arguments
func (l *Logger) Debug(a ...interface{}) {
	l.logAll(optDebug, fmt.Sprint(a...))
}

// Info logs arguments
func (l *Logger) Info(a ...interface{}) {
	l.logAll(optInfo, fmt.Sprint(a...))
}

// Warn logs arguments
func (l *Logger) Warn(a ...interface{}) {
	l.logAll(optWarn, fmt.Sprint(a...))
}

// Error logs arguments
func (l *Logger) Error(a ...interface{}) {
	l.logAll(optError, fmt.Sprint(a...))
}

// Fatal logs arguments
func (l *Logger) Fatal(a ...interface{}) {
	l.logAll(optFatal, fmt.Sprint(a...))
}

// Debugf logs formated arguments
func (l *Logger) Debugf(format string, a ...interface{}) {
	l.logAll(optDebug, fmt.Sprintf(format, a...))
}

// Infof logs formated arguments
func (l *Logger) Infof(format string, a ...interface{}) {
	l.logAll(optInfo, fmt.Sprintf(format, a...))
}

// Warnf logs formated arguments
func (l *Logger) Warnf(format string, a ...interface{}) {
	l.logAll(optWarn, fmt.Sprintf(format, a...))
}

// Errorf logs formated arguments
func (l *Logger) Errorf(format string, a ...interface{}) {
	l.logAll(optError, fmt.Sprintf(format, a...))
}

// Fatalf logs formated arguments
func (l *Logger) Fatalf(format string, a ...interface{}) {
	l.logAll(optFatal, fmt.Sprintf(format, a...))
}

func (l *Logger) Output(calldepth int,c string) {
	if !l.Active {
		return
	}
	for _, r := range l.Receivers {
		// Don't do anything if not wanted
		if !r.Active || r.Level < optError.Level   {
			continue
		}

		// Pre- and suffix
		prefix := ""
		suffix := "\n"

		// Add colors if wanted
		if r.Color {
			prefix += fmt.Sprintf("\x1b[0;%dm", optError.Color)
			suffix = "\x1b[0m" + suffix
		}

		// Print to the logger
		r.logger.Output(calldepth, fmt.Sprintf(prefix+r.Format+suffix, optError.Key, c))
	}
}
func (l *Logger) OutputError(calldepth int,err error) {
	if !l.Active {
		return
	}
	for _, r := range l.Receivers {
		// Don't do anything if not wanted
		if !r.Active || r.Level > optError.Level   {
			continue
		}

		// Pre- and suffix
		prefix := ""
		suffix := "\n"

		// Add colors if wanted
		if r.Color {
			prefix += fmt.Sprintf("\x1b[0;%dm", optError.Color)
			suffix = "\x1b[0m" + suffix
		}

		// Print to the logger
		r.logger.Output(calldepth, fmt.Sprintf(prefix+r.Format+suffix, optError.Key, err.Error()))
	}
}

func (l *Logger) Write(bs []byte) (int,error) {
// Skip everything if logger is disabled
	if !l.Active {
	  return 0,nil
	}
	// Log to all receivers
	for _, r := range l.Receivers {
		// Don't do anything if not wanted
		if !r.Active || optError.Level < r.Level {
			continue
		}

		// Pre- and suffix
		prefix := ""
		suffix := "\n"

		// Add colors if wanted
		if r.Color {
			prefix += fmt.Sprintf("\x1b[0;%dm", optError.Color)
			suffix = "\x1b[0m" + suffix
		}

		// Print to the logger
		r.logger.Output(r.CallDepth, fmt.Sprintf(prefix+r.Format+suffix, optError.Key, string(bs)))

	}
	return 0,nil
}

